#ifndef LIBCELL_ITERATORC_H_
#define LIBCELL_ITERATORC_H_
#define iterator_v lib_cell_iterator_vertices
#define iterator_f lib_cell_iterator_faces
#define iterator_c lib_cell_iterator_cells
#define iterator_edge lib_cell_iterator_edge
#include "Mesh_Frame.h"
#include <tools/intrbtree.h>
#include <tools_node.h>
#ifdef __cplusplus
extern "C"{
#endif

typedef struct iterator_v{
    Int_RB_Tree_Trav it;
    template_v** value;
    int i;
}iterator_v;

static inline void iterator_v_init(iterator_v* it)
{
    int_rb_tree_trav_init(&(it->it));
    it->i=0;
    it->value=NULL;
}
static inline void iterator_v_next(iterator_v* vv_)
{
    if(vv_->value==NULL)
    {
        vv_->it.next(&(vv_->it));
    }
    else
    {
        (vv_->i)++;

    } 
}
static inline template_v* iterator_v_quote(iterator_v vv_)
{
    return vv_.value==NULL?((template_v*)((vv_.it).it->data)):vv_.value[vv_.i]; 
}
static inline int iterator_v_is_not_equal(iterator_v v_1,iterator_v v_2)
{
    if(v_1.value==v_2.value&&v_1.i==v_2.i&&v_1.it.it==v_2.it.it)
    {
        return 0;
    }
    return 1; 
}
typedef struct iterator_f{
    Int_RB_Tree_Trav it;
    Node node;
}iterator_f;
static inline void iterator_f_init(iterator_f*it)
{
    int_rb_tree_trav_init(&(it->it));
    Node_init(&(it->node));
}
static inline void iterator_f_next(iterator_f*f_)
{
    if(f_->node.value==NULL)
    {
        f_->it.next(&(f_->it));
    }
    else
    {
        if(f_->node.Prev==NULL)
        {
            Node_init(&(f_->node));
        }
        else
        {
            f_->node=*((Node*)(f_->node.Prev)); 
        }
    } 
}
static inline int iterator_f_is_not_equal(iterator_f f_1,iterator_f f_2)
{
    if(f_1.node.value==f_2.node.value&&f_1.it.it==f_2.it.it)
    {
        return 0;
    } 
    return 1;
}
static inline template_f* iterator_f_quote(iterator_f f_)
{
    return  f_.node.value==NULL?((template_f*)((f_.it).it->data)):((template_f*)((f_.node).value));
}

typedef struct iterator_c{
    Int_RB_Tree_Trav it;
    Node node;
}iterator_c;
static inline void iterator_c_init(iterator_c*it)
{
    int_rb_tree_trav_init(&(it->it));
    Node_init(&(it->node));
}

static inline void iterator_c_next(iterator_c* c_)
{
    if(c_->node.value==NULL)
    {
        c_->it.next(&(c_->it));
    }
    else
    {
        if(c_->node.Next==NULL)
        {
            Node_init(&(c_->node));
        }
        else
        {
            c_->node=*((Node*)(c_->node.Next)); 
        }
    }
}
static inline int iterator_c_is_not_equal(iterator_c c_1,iterator_c c_2)
{
    if(c_1.node.value==c_2.node.value&&c_1.it.it==c_2.it.it)
    {
        return 0;
    }
    return 1; 
}
static inline template_c* iterator_c_quote(iterator_c c_)
{
    return c_.node.value==NULL?((template_c*)((c_.it).it->data)):((template_c*)((c_.node).value));

}
typedef struct iterator_hf
{
    Int_RB_Tree_Trav it;
    Node node;
}iterator_hf;

static inline void iterator_hf_init(iterator_hf* hf_)
{
    int_rb_tree_trav_init(&(hf_->it));
    Node_init(&(hf_->node));

}
static inline void iterator_hf_next(iterator_hf*it)
{
    if(it->node.value==NULL)
    {
        it->it.next(&(it->it));
    } 
    else
    {
        if(it->node.Prev==NULL)
        {
            Node_init(&(it->node));
        }
        else
        {
            it->node=*((Node*)(it->node.Prev)); 
        }
    }
}
static inline int iterator_hf_is_not_equal(iterator_hf it1,iterator_hf it2 )
{
    if(it1.node.value==it2.node.value&&it1.it.it==it2.it.it)
    {
        return 0;
    }
    return 1;
} 
static inline template_hf* iterator_hf_quote(iterator_hf it)
{
    return it.node.value==NULL?((template_hf*)((it.it).it->data)):((template_hf*)((it.node).value));
}
typedef struct iterator_edge{
    template_f* f;
    template_v* v;
    template_f* mark;

}iterator_edge;


static inline void iterator_edge_init(iterator_edge* ie)
{
    ie->f=NULL;
    ie->v=NULL;
    ie->mark=NULL;
}

static inline void iterator_edge_next(iterator_edge*ie)
{
    if(ie->f==NULL||ie->v==NULL)
    {
        ie->f=NULL;ie->v=NULL;
        return ;
    }
    template_v* v=NULL;template_f* f=NULL;
    for(int i=0;i<ie->f->vertices_size;i++)
    {
        if(ie->f->vertices[i]!=ie->v)
        {
            v=ie->f->vertices[i];
            break;
        }
    }
    ie->v=v;
    if(v==NULL)
    {
        ie->f=NULL;
        return ;
    }
    for(Node* nit=v->faces;nit!=NULL;nit=(Node*)(nit->Next))
    {
        if(nit->value!=ie->f)
        {
            f=(template_f*)(nit->value);
            break;
        }
    }
    ie->f=f;

    if(ie->f==ie->mark)
    {
        ie->v=NULL;
        ie->f==NULL;
    }
    return; 
}
static inline int iterator_edge_is_not_equal(iterator_edge ie1,iterator_edge ie2)
{
    if(ie1.v==ie2.v&&ie1.f==ie2.f)
    {
        return 0;
    }
    return 1; 
}

#ifdef __cplusplus
}
#endif
#undef iterator_v 
#undef iterator_f 
#undef iterator_c 
#undef iterator_edge
#endif
